/*
 * src/interfaces/ecpg/preproc/type.h
 */
#ifndef _ECPG_PREPROC_TYPE_H
#define _ECPG_PREPROC_TYPE_H

#include "ecpgtype.h"

struct ECPGtype;
struct ECPGstruct_member
{
	char	   *name;
	struct ECPGtype *type;
	struct ECPGstruct_member *next;
};

struct ECPGtype
{
	enum ECPGttype type;
	char	   *type_name;		/* 对于结构体和联合体类型，它是结构体名称 */
	char	   *size;			/* 对于数组，它是元素的数量。对于varchar，它是区域的最大大小。 */
	char	   *struct_sizeof;	/* 对于结构体，这表示sizeof()类型的字符串 */
	union
	{
		struct ECPGtype *element;	/* 对于数组，这表示元素的类型 */
		struct ECPGstruct_member *members;	/* 指向成员列表的指针。 */
	}			u;
	int			counter;
};

/* 一切都是通过malloc分配的。 */
void		ECPGmake_struct_member(const char *, struct ECPGtype *, struct ECPGstruct_member **);
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, char *, int);
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, char *);
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype, char *, char *);
struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *);

/* 释放一个类型。 */
void		ECPGfree_struct_member(struct ECPGstruct_member *);
void		ECPGfree_type(struct ECPGtype *);

/* 转储一个类型。
   类型被转储为：
   type-tag <逗号> reference-to-variable <逗号> arrsize <逗号> size <逗号>
   其中：
   type-tag 是简单类型或varchar之一。
   reference-to-variable 可以是对结构体元素的引用。
   arrsize 是数组获取时数组的大小。否则为0。
   size 是如果是varchar时的最大大小。否则是变量的大小
	   （必须进行结构体的数组获取）。
 */
void		ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const int,
							const char *, struct ECPGtype *, const int,
							const char *, const char *, char *,
							const char *, const char *);

/* 一个简单的结构体，用于保存一个变量及其类型。 */
struct ECPGtemp_type
{
	struct ECPGtype *type;
	const char *name;
};

extern const char *ecpg_type_name(enum ECPGttype type);

/* 一些用于 whenever 语句的内容 */
enum WHEN_TYPE
{
	W_NOTHING,
	W_CONTINUE,
	W_BREAK,
	W_SQLPRINT,
	W_GOTO,
	W_DO,
	W_STOP
};

struct when
{
	enum WHEN_TYPE code;
	char	   *command;
	char	   *str;
};

struct index
{
	char	   *index1;
	char	   *index2;
	char	   *str;
};

struct su_symbol
{
	char	   *su;
	char	   *symbol;
};

struct prep
{
	char	   *name;
	char	   *stmt;
	char	   *type;
};

struct exec
{
	char	   *name;
	char	   *type;
};

struct this_type
{
	char	   *type_storage;
	enum ECPGttype type_enum;
	char	   *type_str;
	char	   *type_dimension;
	char	   *type_index;
	char	   *type_sizeof;
};

struct _include_path
{
	char	   *path;
	struct _include_path *next;
};

struct cursor
{
	char	   *name;
	char	   *function;
	char	   *command;
	char	   *connection;
	bool		opened;
	struct arguments *argsinsert;
	struct arguments *argsinsert_oos;
	struct arguments *argsresult;
	struct arguments *argsresult_oos;
	struct cursor *next;
};

struct declared_list
{
	char	   *name;
	char	   *connection;
	struct declared_list *next;
};

struct typedefs
{
	char	   *name;
	struct this_type *type;
	struct ECPGstruct_member *struct_member_list;
	int			brace_level;
	struct typedefs *next;
};

/*
 * 关于已定义符号（宏）的信息，来自 -D 命令行开关
 * 或程序中的 define 命令。这些被存储在一个简单的列表中。
 * 因为 ecpg 支持每次运行编译多个文件，我们必须记住
 * 命令行定义并能够恢复到这些定义；这促使
 * 将 cmdvalue 单独存储于 value。
 * name 和 value 是分别通过 malloc 分配的字符串；cmdvalue 通常不是。
 * used 为 NULL，除非我们当前正在扩展宏，在这种情况下
 * 它指向扫描宏之前的缓冲区；我们在返回到该缓冲区时将其重置为 NULL。
 * 这用于防止宏的递归扩展。
 */
struct _defines
{
	char	   *name;			/* 符号的名称 */
	char	   *value;			/* 当前值，如果未定义则为NULL */
	const char *cmdvalue;		/* 在命令行上设置的值，或NULL */
	void	   *used;			/* 缓冲区指针，或NULL */
	struct _defines *next;		/* 列表链接 */
};

/* 这是一个变量名称和类型的链表。 */
struct variable
{
	char	   *name;
	struct ECPGtype *type;
	int			brace_level;
	struct variable *next;
};

struct arguments
{
	struct variable *variable;
	struct variable *indicator;
	struct arguments *next;
};

struct descriptor
{
	char	   *name;
	char	   *connection;
	struct descriptor *next;
};

struct assignment
{
	char	   *variable;
	enum ECPGdtype value;
	struct assignment *next;
};

enum errortype
{
	ET_WARNING, ET_ERROR
};

struct fetch_desc
{
	char	   *str;
	char	   *name;
};

struct describe
{
	int			input;
	char	   *stmt_name;
};

#endif							/* _ECPG_PREPROC_TYPE_H */
